﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;

namespace HML
{
    /// <summary>
    /// 主题控制器
    /// </summary>
    [Description("主题控制器")]
    [DefaultProperty("StyleForm")]
    [TypeConverter(typeof(SkinStyleControllerConverter))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(SkinStyleController), "Controls.SkinStyleController.Resources.SkinStyleController.bmp")]
    public class SkinStyleController : Component, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(SkinStyleController)).GetName().Name, typeof(SkinStyleController).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinStyleController SkinController
        {
            get { return null; }
            set { }
        }

        private SkinEnabledState skinEnabled = SkinEnabledState.True;
        /// <summary>
        /// 主题是否启用 (这里只建议使用 True和False 两种状态，因为Auto等于False)
        /// </summary>
        [Description("主题是否启用 (这里只建议使用 True和False 两种状态，因为Auto等于False)")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.True)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;

                if (this.StyleForm != null)
                {
                    if (this.skinEnabled == SkinEnabledState.True)
                    {
                        this.styleForm.BackColorChanged += this.StyleForm_BackColorChanged;
                        this.styleForm.ForeColorChanged += this.StyleForm_ForeColorChanged;
                        this.styleForm.Disposed += this.StyleForm_Disposed;

                        this.SkinBackColorChangeing = true;
                        this.styleForm.BackColor = this.StyleAppearance.BackColor;
                        this.SkinBackColorChangeing = false;

                        this.SkinForeColorChangeing = true;
                        this.styleForm.ForeColor = this.StyleAppearance.TextColor;
                        this.SkinForeColorChangeing = false;
                    }
                    else
                    {
                        this.styleForm.BackColorChanged -= this.StyleForm_BackColorChanged;
                        this.styleForm.ForeColorChanged -= this.StyleForm_ForeColorChanged;
                        this.styleForm.Disposed -= this.StyleForm_Disposed;

                        this.styleForm.BackColor = Color.Empty;
                        this.styleForm.ForeColor = Color.Empty;
                    }
                }

                if (this.SkinEnabled == SkinEnabledState.True)
                {
                    SkinManager.SyncSkinValueToProperty(this);
                }
                foreach (ISkinObject skinObject in this.skinObjects)
                {
                    skinObject.OnSkinChanged();
                }
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;

                SkinManager.SyncSkinValueToProperty(this);

                if (this.StyleForm != null && this.SkinEnabled == SkinEnabledState.True)
                {
                    this.SkinBackColorChangeing = true;
                    this.styleForm.BackColor = this.StyleAppearance.BackColor;
                    this.SkinBackColorChangeing = false;

                    this.SkinForeColorChangeing = true;
                    this.styleForm.ForeColor = this.StyleAppearance.TextColor;
                    this.SkinForeColorChangeing = false;
                }
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        private Form styleForm = null;
        /// <summary>
        /// 主题要绑定的窗体
        /// </summary>
        [Description("主题要绑定的窗体")]
        [Category("杂项")]
        [PropertyOrder(-194)]
        [DefaultValue(null)]
        [TypeConverter(typeof(StyleFormConverter))]
        public Form StyleForm
        {
            get { return this.styleForm; }
            set
            {
                if (this.styleForm == value)
                    return;

                if (this.styleForm != null && this.SkinEnabled == SkinEnabledState.True)
                {
                    this.styleForm.BackColorChanged -= this.StyleForm_BackColorChanged;
                    this.styleForm.ForeColorChanged -= this.StyleForm_ForeColorChanged;
                    this.styleForm.Disposed -= this.StyleForm_Disposed;

                    this.styleForm.BackColor = Color.Empty;
                    this.styleForm.ForeColor = Color.Empty;
                }

                this.styleForm = value;

                if (value != null && this.SkinEnabled == SkinEnabledState.True)
                {
                    this.styleForm.BackColorChanged += this.StyleForm_BackColorChanged;
                    this.styleForm.ForeColorChanged += this.StyleForm_ForeColorChanged;
                    this.styleForm.Disposed += this.StyleForm_Disposed;

                    this.SkinBackColorChangeing = true;
                    this.styleForm.BackColor = this.StyleAppearance.BackColor;
                    this.SkinBackColorChangeing = false;

                    this.SkinForeColorChangeing = true;
                    this.styleForm.ForeColor = this.StyleAppearance.TextColor;
                    this.SkinForeColorChangeing = false;
                }
            }
        }

        private void StyleForm_BackColorChanged(object sender, EventArgs e)
        {
            if (!this.SkinBackColorChangeing)
            {
                this.SkinBackColorChangeing = true;
                this.styleForm.BackColor = this.StyleAppearance.BackColor;
                this.SkinBackColorChangeing = false;
            }
        }

        private void StyleForm_ForeColorChanged(object sender, EventArgs e)
        {
            if (!this.SkinForeColorChangeing)
            {
                this.SkinForeColorChangeing = true;
                this.styleForm.ForeColor = this.StyleAppearance.TextColor;
                this.SkinForeColorChangeing = false;
            }
        }

        private void StyleForm_Disposed(object sender, EventArgs e)
        {
            this.StyleForm = null;
        }

        public void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);

            if (this.StyleForm != null && this.SkinEnabled == SkinEnabledState.True)
            {
                this.SkinBackColorChangeing = true;
                this.styleForm.BackColor = this.StyleAppearance.BackColor;
                this.SkinBackColorChangeing = false;

                this.SkinForeColorChangeing = true;
                this.styleForm.ForeColor = this.StyleAppearance.TextColor;
                this.SkinForeColorChangeing = false;
            }

            foreach (ISkinObject skinObject in this.skinObjects)
            {
                if (this.SkinEnabled == SkinEnabledState.True || skinObject.SkinEnabled == SkinEnabledState.True)
                {
                    skinObject.OnSkinChanged();
                }
            }
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region 字段

        /// <summary>
        ///主题方式正在修改BackColor
        /// </summary>
        private bool SkinBackColorChangeing = false;
        /// <summary>
        ///主题方式正在修改ForeColor
        /// </summary>
        private bool SkinForeColorChangeing = false;

        /// <summary>
        /// 要管理的SkinObject集合
        /// </summary>
        private List<ISkinObject> skinObjects = new List<ISkinObject>();

        #endregion

        public SkinStyleController()
        {
            this.OnSkinChanged();
        }

        public SkinStyleController(IContainer container) : this()
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            container.Add(this);

            if (!SkinManager.StyleControllers.Contains(this))
            {
                SkinManager.StyleControllers.Add(this);
            }
        }

        #region 重写

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.styleForm != null)
                {
                    this.StyleForm = null;
                }
                ISkinObject[] skinObjectsArr = this.skinObjects.ToArray();
                for (int i = 0; i < skinObjectsArr.Length; i++)
                {
                    if (skinObjectsArr[i].SkinController != null)
                    {
                        skinObjectsArr[i].SkinController = null;
                    }
                }
                if (SkinManager.StyleControllers.Contains(this))
                {
                    SkinManager.StyleControllers.Remove(this);
                }
            }
            base.Dispose(disposing);
        }

        #endregion

        #region 公开方法

        /// <summary>
        /// 主题对象添加到主题管理器中
        /// </summary>
        /// <param name="skinObject">主题对象</param>
        public void AddSkinObject(ISkinObject skinObject)
        {
            if (skinObject == null)
                return;

            if (this.skinObjects.Find(a => a == skinObject) == null)
            {
                this.skinObjects.Add(skinObject);
                skinObject.OnSkinChanged();
            }
        }
        /// <summary>
        /// 从主题管理器中移除主题对象
        /// </summary>
        /// <param name="skinObject">主题对象</param>
        public void RemoveSkinObject(ISkinObject skinObject)
        {
            if (skinObject == null)
                return;

            this.skinObjects.Remove(skinObject);
            skinObject.OnSkinChanged();
        }

        /// <summary>
        /// 添加到主题管理器监听中
        /// </summary>
        public void AddSkinListener()
        {
            if (!SkinManager.StyleControllers.Contains(this))
            {
                SkinManager.StyleControllers.Add(this);
            }
        }

        /// <summary>
        /// 从主题管理器监听中移除
        /// </summary>
        public void RemoveSkinListener()
        {
            if (SkinManager.StyleControllers.Contains(this))
            {
                SkinManager.StyleControllers.Remove(this);
            }
        }


        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBackColor = SystemColors.Control;
            private readonly Color defaultBackColor = SystemColors.Control;
            private Color backColor = SystemColors.Control;
            /// <summary>
            /// 背景色
            /// </summary>
            [Description("背景色")]
            [Category("杂项")]
            [PropertyOrder(-196)]
            [SkinProperty(true, false)]
            [EditorBrowsable(EditorBrowsableState.Never)]
            public Color BackColor
            {
                get { return this.skinBackColor; }
                set
                {
                    if (value == Color.Empty)
                        value = this.defaultBackColor;

                    if (this.skinBackColor == value)
                        return;

                    this.backColor = value;
                    this.skinBackColor = value;
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return false;
            }
            private void ResetBackColor()
            {

            }

            private Color skinTextColor = SystemColors.WindowText;
            private readonly Color defaultTextColor = SystemColors.WindowText;
            private Color textColor = SystemColors.WindowText;
            /// <summary>
            /// 前景色
            /// </summary>
            [Description("前景色")]
            [Category("杂项")]
            [PropertyOrder(-194)]
            [SkinProperty(true, false)]
            [EditorBrowsable(EditorBrowsableState.Never)]
            public Color TextColor
            {
                get { return this.skinTextColor; }
                set
                {
                    if (value == Color.Empty)
                        value = this.defaultTextColor;

                    if (this.skinTextColor == value)
                        return;

                    this.textColor = value;
                    this.skinTextColor = value;
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return false;
            }
            private void ResetTextColor()
            {

            }

            #endregion

        }

        #endregion

    }

}
